
package com.coda.clouddisk.aspect;

import com.coda.clouddisk.annotation.Loggable;
import com.coda.clouddisk.context.BaseContext;
import com.coda.clouddisk.entity.User;
import com.coda.clouddisk.entity.UserLog;
import com.coda.clouddisk.exception.BaseException;
import com.coda.clouddisk.mapper.UserLogMapper;
import com.coda.clouddisk.mapper.UserMapper;
import com.coda.clouddisk.message.MessageContext;
import com.coda.clouddisk.utils.EntityToMap;
import com.coda.clouddisk.utils.MapToEntity;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 用户操作日志
 */
@Component
@Aspect
@Slf4j
@Transactional
public class UserLogAspect {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserLogMapper userLogMapper;

    /**
     * 切入点
     */
    // 定义切点，拦截所有带有@Loggable注解的方法
    @Pointcut("@annotation(com.coda.clouddisk.annotation.Loggable)")
    public void loggableMethods() {
    }
    @Around("loggableMethods()")
    public Object logUserAction(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Loggable loggable = signature.getMethod().getAnnotation(Loggable.class);

            if (loggable == null) {
                return joinPoint.proceed();
            }

            // 获取方法参数
            Object[] args = joinPoint.getArgs();
            String params = args.length > 0 ? args[0].toString() : "";

            // 获取IP地址
            String ipAddress = request.getRemoteAddr();

            // 记录开始时间
            float startTime = System.currentTimeMillis();
            // 执行目标方法
            Object result = joinPoint.proceed();
            // 记录结束时间
            long endTime = System.currentTimeMillis();
            // 计算耗时
            float spendTime = endTime - startTime;

            // 获取方法名
            String actionName = joinPoint.getSignature().getName();
            // 获取注解的value属性值
            String name = loggable.value();

            // 创建日志对象
            UserLog userLog = new UserLog();
            userLog.setName(signature.getMethod().getName());  // 设置操作方法名
            userLog.setDescription(name);  //描述
            userLog.setSerial(0);  //设置序号
            userLog.setBusinessDate(new Date());  //设置业务时间
            userLog.setIpAddress(ipAddress);  // 设置ip地址
            userLog.setDoDate(new Date());  // 设置执行时间
            userLog.setActionName(actionName);  // 设置操作名
            userLog.setParams(params);   // 设置传递参数
            userLog.setSpendTime(spendTime);  // 设置消耗时间
            userLog.setStatus("1000");
            System.out.println(signature.getMethod().getName());

            //判断是否为登录操作
            if (signature.getMethod().getName().equals("login")) {
                //获取方法参数
                Object[] args1 = joinPoint.getArgs();
                User userParams = (User) args1[0];  //获取user对象
                Map<String, Object> map = new HashMap<>();
                map.put("number",userParams.getNumber());
                User userInfo = (User) userMapper.find(map);  //通过number查找user
                setUserParams(userLog, userInfo);
                Map<String, Object> userLogMap1 = EntityToMap.convertObjectToMap(userLog);
                // 保存日志
                userLogMapper.add(userLogMap1);
                return result;
            }

            //判断是否为注册操作
            if (signature.getMethod().getName().equals("Register")) {
                //获取方法参数
                Object[] args1 = joinPoint.getArgs();
                User userParams = (User) args1[0];  //获取user对象
                userLog.setByUserName(userParams.getNumber());

                // 保存日志
                Map<String, Object> userLogMap2 = EntityToMap.convertObjectToMap(userLog);
                userLogMapper.add(userLogMap2);
                return result;
            }

            HashMap<String, Object> map = new HashMap<>();
            map.put("id",BaseContext.getCurrentId());
            User userInfo = (User) userMapper.find(map);
            setUserParams(userLog, userInfo);

            Map<String, Object> userLogMap3 = EntityToMap.convertObjectToMap(userLog);
            // 保存日志
            userLogMapper.add(userLogMap3);
            return result;
        } catch (RuntimeException e) {
            throw new BaseException(MessageContext.ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 设置用户参数
     *
     * @param userLog
     * @param userInfo
     */
    private void setUserParams(UserLog userLog, User userInfo) {
        userLog.setByUserName(userInfo.getNumber());  //设置用户名
        userLog.setByUser(userInfo.getId());  // 设置创建者
        userLog.setUser(userInfo);  //设置用户
    }

    public static void main(String[] args) throws Exception {
        Map<String, Object> map = new HashMap();
        User user1 = new User();
        user1.setPassword("111");
        user1.setId("111");
        map.put("id","001");
        map.put("password","fjadlk;");
        map.put("number","faji");
        map.put("user",user1);

        User user = MapToEntity.convertMapToObject(map, User.class);
        System.out.println(user.toString());
        System.out.println(user.getId());
        System.out.println(user.getUser().getId());

    }


}